#include <stdio.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>

#define MSGTYPE_R 11
#define MSGTYPE_L 22
#define MSGTYPE_Q 33
#define MSGTYPE_H 44

int user_registration(int sockfd);
int user_login(int sockfd);
void user_menu(int sockfd);
int user_query(int sockfd);
int user_history(int sockfd);

typedef struct {
	int type;	// 记录用户的操作状态
	char name[32];	// 用户名称
	char date[300];	// 数据部分
}MSG_TXT;

MSG_TXT cur_user = {0};

int main(int argc, const char **argv){
	if(argc != 3){
		puts("输入IP地址和端口号来连接服务器");
		exit(-1);
	}
	// 创建一个套接字作为网络连接的端点
	int sockfd = socket(AF_INET, SOCK_STREAM, 0);
	if(sockfd == -1){
		perror("请检查网络连接情况");
		exit(-1);
	}

	// 将套接字绑定
	struct sockaddr_in client_addr = {0};
	client_addr.sin_family = AF_INET;
	client_addr.sin_port = 0;	// 赋值0系统会自动分配
	client_addr.sin_addr.s_addr = htonl(INADDR_ANY);
	int ret = bind(sockfd, (struct sockaddr *)&client_addr, sizeof(client_addr));
	if(ret == -1){
		perror("请检查网络信息");
		exit(-1);
	}

	// 尝试连接服务器
	struct sockaddr_in server_addr = {0};
	server_addr.sin_family = AF_INET;
	server_addr.sin_port = htons(atoi(argv[2]));
	server_addr.sin_addr.s_addr = inet_addr(argv[1]);
	ret = connect(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr));
	if(ret == -1){
		perror("请检查服务器信息或者联系服务器维护人员");
		exit(-1);
	}

	// 开始向服务器发送请求
	while(1){
        printf("------------------------------------------\n");
        printf("----------------电子词典项目----------------\n");
        printf("------------------------------------------\n");
        printf("--------1.注册-----2.登陆-----3.退出--------\n");
        printf("------------------------------------------\n");
        printf("请输入你的选择:\n");
		int client_choice = 0;
		scanf("%d", &client_choice);

		switch(client_choice){
			case 1:
				user_registration(sockfd);
				break;
			case 2:
				if (user_login(sockfd)){
					// 跳转二级菜单
					user_menu(sockfd);
				}
				
				break;
			case 3:
				close(sockfd);
				exit(0);
			default:
				printf("请输入正确的选项\n");
		}
	}
}

/// @brief 用户注册
/// @param sockfd 套接字
/// @return 0 注册失败 1 注册成功
int user_registration(int sockfd){
	// 创建一个MSG_T结构体
	MSG_TXT msg = {0};
	msg.type = MSGTYPE_R;
	printf("请输入用户名:");
	scanf("%s", msg.name);
	printf("请输入密码:");
	scanf("%s", msg.date);

	// 发送请求
	int ret = send(sockfd, &msg, sizeof(msg), 0);
	if(ret == -1){
		perror("发送失败,请重新尝试");
		return -1;
	}


	// 接收服务器的响应
	memset(&msg.date, 0, sizeof(msg.date));
	ret = recv(sockfd, &msg, sizeof(msg), 0);

	if(ret == -1){
		perror("接收失败,请重新尝试");
		exit(-1);
	}
	else if(ret == 0){
		printf("服务器已经关闭,请重新尝试\n");
		exit(-1);
	}
	else{
		printf("%s\n", msg.date);
	}

	return 0;
}

/// @brief 用户登陆
/// @param sockfd 套接字
/// @return 0 登陆失败 1 登陆成功
int user_login(int sockfd){
	// 创建一个MSG_T结构体
	MSG_TXT msg = {0};
	msg.type = MSGTYPE_L;
	printf("请输入用户名:");
	scanf("%s", msg.name);
	printf("请输入密码:");
	scanf("%s", msg.date);
	strcpy(cur_user.name, msg.name);
	strcpy(cur_user.date, msg.date);

	// 向服务器发送请求
	int ret = send(sockfd, &msg, sizeof(msg), 0);
	if(ret == -1){
		perror("发送失败,请重新尝试");
		return -1;
	}

	// 接收服务器的响应
	memset(&msg.date, 0, sizeof(msg.date));
	ret = recv(sockfd, &msg, sizeof(msg), 0);
	if(ret == -1){
		perror("接收失败,请重新尝试");
		exit(-1);
	}
	else if(ret == 0){
		printf("服务器已经关闭,请重新尝试\n");
		exit(-1);
	}
	else{
		if(strcmp(msg.date, "登陆成功") == 0){
			printf("登陆成功\n");
			return 1;
		}else{
			printf("%s\n", msg.date);
			return 0;
		}
	}
}

/// @brief 用户二级菜单
/// @param sockfd 套接字
/// @return
void user_menu(int sockfd){
	while(1){
        printf("--------------------------------------------\n");
        printf("---------------欢迎使用电子词典----------------\n");
        printf("--------------------------------------------\n");
        printf("-------1.查询-----2.历史记录-----3.退出--------\n");
        printf("--------------------------------------------\n");
        printf("请输入你的选择:\n");

		int client_choice = 0;
		scanf("%d", &client_choice);
		switch(client_choice){
			case 1:
				user_query(sockfd);
				break;
			case 2:
				user_history(sockfd);
				break;
			case 3:
				return;
			default:
				printf("请输入正确的选项\n");
		}
	}
}

/// @brief 用户查询
/// @param sockfd 套接字
/// @return
int user_query(int sockfd){
	// 创建一个MSG_T结构体
	MSG_TXT msg = {0};
	msg.type = MSGTYPE_Q;
	strcpy(msg.name, cur_user.name);

	while(1){
		printf("请输入需要查询的词条，输入-1结束程序\n");
		scanf("%s", msg.date);
		if(strcmp(msg.date, "-1") == 0){
			return 0;
		}

		// 发送请求
		int ret = send(sockfd, &msg, sizeof(msg), 0);
		if(ret == -1){
			perror("发送失败,请重新尝试");
			exit(-1);
		}

		// 接收服务器的响应
		memset(&msg.date, 0, sizeof(msg.date));
		ret = recv(sockfd, &msg, sizeof(msg), 0);
		if(ret == -1){
			perror("接收失败,请重新尝试");
			exit(-1);
		}
		else if(ret == 0){
			printf("服务器已经关闭,请重新尝试\n");
			exit(-1);
		}else{
			printf("%s\n", msg.date);
		}
	}
}

/// @brief 用户历史记录
/// @param sockfd 套接字
/// @return 
int user_history(int sockfd){
	printf("用户历史记录\n");

	// 创建一个MSG_T结构体
	MSG_TXT msg = {0};
	msg.type = MSGTYPE_H;
	strcpy(msg.name, cur_user.name);
	
	// 发送请求
	int ret = send(sockfd, &msg, sizeof(msg), 0);
	if(ret == -1){
		perror("发送失败,请重新尝试");
		exit(-1);
	}

	// 接收服务器的响应
	while (1){
		ret = recv(sockfd, &msg, sizeof(msg), 0);
		if(ret > 0){
			if(strcmp(msg.date, "无") == 0){
				break;
			}
			printf("%s\n", msg.date);
		}else if(ret == 0){
			printf("服务器已经关闭,请重新尝试\n");
			exit(-1);
		}else{
			perror("接收失败,请重新尝试");
			exit(-1);
		}
	}
}